﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using HtmlExtractor;
using System.Xml.Linq;
using HtmlExtractor.Output;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;

namespace Reader.Domain
{
    public partial class BookChapter
    {
        public string BookPageUri
        {
            get;
            set;
        }
       
        public string BookContentUri
        {
            get;
            set;
        }
        public string TextContent
        {
            get;
            set;
        }        
        public List<string> ImageContent
        {
            get;
            set;
        }
        public string NextUri
        {
            get;
            set;
        }
        public string TextUri
        {
            get;
            set;
        }
        public string PreviousUri
        {
            get;
            set;
        }
        public string Title
        {
            get;
            set;
        }
        public string UpdateTime
        {
            get;
            set;
        }
    }
    public partial class BookChapter
    {
        public static bool IsImageContent(XDocument rdoc)
        {
            return rdoc.Descendants(Context.ImageToolsNamespace + "AnimatedImage").Select((a) => a.Attribute("Source").Value).Where((ss) => !string.IsNullOrEmpty(ss)).Count() > 0;
        }
        public static string GetNextUri(XDocument rdoc)
        {
           return (string)rdoc.Descendants(Context.DefaultNamespace + "HyperlinkButton").Where(e => e.Attribute("Name").Value == "Next").Single().Attribute("CommandParameter");
        }
        public static string GetPreviousUri(XDocument rdoc)
        {
            return (string)rdoc.Descendants(Context.DefaultNamespace + "HyperlinkButton").Where(e => e.Attribute("Name").Value == "Previous").Single().Attribute("CommandParameter");
            
        }
        public static string GetContentUri(XDocument rdoc)
        {
            return (string)rdoc.Descendants(Context.DefaultNamespace + "HyperlinkButton").Where(e => e.Attribute("Name").Value == "Content").Single().Attribute("CommandParameter");

        }
        public static bool IsEnd(XDocument rdoc)
        {
            return GetNextUri(rdoc) == GetContentUri(rdoc);
        }
        public static bool IsFirst(XDocument rdoc)
        {
            return GetPreviousUri(rdoc) == GetContentUri(rdoc);
        }
        public static List<XElement> GetImage(XDocument rdoc)
        {
            IEnumerable<XElement> images = rdoc.Descendants(Context.ImageToolsNamespace + "AnimatedImage");
            return images.ToList();
        }

        public static string GetBookName(XDocument rdoc)
        {
            return (string)rdoc.Descendants(Context.DefaultNamespace + "TextBlock").Where(e => ((string)(e.Attribute("Name")) == "BookName")).Single().Attribute("Text");
        }
        public static string GetTextUri(XDocument rdoc)
        {
            return (string)rdoc.Descendants(Context.DefaultNamespace + "TextBlock").Where(e => ((string)(e.Attribute("Name")) == "TextUri")).Single().Attribute("Text");
        }
        public static XElement GetTextContent(XDocument rdoc)
        {
            return rdoc.Descendants(Context.DefaultNamespace + "RichTextBox").SingleOrDefault();
        }
        public static void RemoveTextContent(XDocument rdoc)
        {
            if (IsImageContent(rdoc))
            {
                //图片章节，去除文本节点
                if (rdoc.Descendants(Context.DefaultNamespace + "RichTextBox").Count() != 0)
                {
                    rdoc.Descendants(Context.DefaultNamespace + "RichTextBox").Remove();
                }
            }
        }
      
        /// <summary>
        ///如果缓存，则保存到Cache文件夹，否则保存到sites文件夹         
        /// </summary>
        /// <param name="rdoc"></param>
        public static void SaveImage(XDocument rdoc,bool isCache,TimeSpan? cacheTime)
        {
            if (IsImageContent(rdoc))
            {
                foreach (XElement image in GetImage(rdoc))
                {
                    string imageUri = image.Attribute("Source").Value;
                    if (!string.IsNullOrEmpty(imageUri))
                    {
                        string imagePath = null;
                        if (!Cache.Current.TryGet(imageUri, out imagePath))
                        {
                            if(isCache)
                                imagePath = Path.Combine(ReaderPath.CacheDirectory, ReaderPath.ConvertToWinPath(imageUri));
                            else
                                imagePath = ReaderPath.GetSiteFileName(imageUri);                           
                            SaveFile.SaveImage(imageUri, imagePath, isCache,cacheTime);                           
                        }
                    }
                }
            }            
        }
       
       
       
        /// <summary>
        /// 如果是图片去掉文本节点
        /// </summary>
        /// <param name="html"></param>
        /// <param name="uri"></param>
        /// <param name="template"></param>
        /// <returns></returns>
        public static XDocument GenerateChapterXaml(string html, string uri, string template)
        {
            XDocument rdoc = SaveFile.GenerateXaml(html, uri, template);
            RemoveTextContent(rdoc);
            return rdoc;
        }
        public static void SaveQidianFile(XDocument chapterDoc, string chapterUri, string template)
        {
            if (new Uri(chapterUri).Host == "www.qidian.com")
            {
                string textUri = GetTextUri(chapterDoc);
                if (!string.IsNullOrEmpty(textUri))
                {
                    if (Uri.IsWellFormedUriString(textUri, UriKind.Absolute))
                    {
                        string cachePath = "";
                        if (!Cache.Current.TryGet(textUri, out cachePath))
                        {
                            string localPath = ReaderPath.GetSiteFileName(textUri);
                            if (!File.Exists(localPath))
                            {
                                WebClient client = new WebClient();
                                client.Encoding = new Gb2312Encoding();
                                client.DownloadStringAsync(new Uri(textUri));
                                client.DownloadStringCompleted += (s, args) =>
                                {
                                    if (args.Error == null)
                                    {
                                        XDocument textDoc = GenerateChapterXaml(args.Result, textUri, template);
                                        File.WriteAllText(localPath, textDoc.ToString());
                                    }
                                };
                            }
                        }
                        else
                        {
                            //从缓存拷贝到loacl
                            //XDocument rdoc = XDocument.Parse(File.ReadAllText(cachePath));
                            string loaclPath = ReaderPath.GetSiteFileName(textUri);
                            if (!File.Exists(loaclPath))
                            {
                                File.Copy(cachePath, loaclPath);
                                
                            }
                        }
                       
                        
                    }
                }
            }
        }
        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="docUri"></param>
        /// <param name="template"></param>
        public static void SaveChapterXamlFile(string docUri, string template)
        {  
            string cachePath = "";
            if (!Cache.Current.TryGet(docUri, out cachePath))
            {
                string localPath= ReaderPath.GetSiteFileName(docUri);
                if (!File.Exists(localPath))
                {
                    WebClient client = new WebClient();
                    client.Encoding = new Gb2312Encoding();
                    client.DownloadStringAsync(new Uri(docUri));
                    client.DownloadStringCompleted += (s, args) =>
                    {
                        if (args.Error == null)
                        {
                            XDocument rdoc = BookChapter.GenerateChapterXaml(args.Result, docUri, template);

                            if (docUri != GetContentUri(rdoc))
                            {
                                SaveQidianFile(rdoc, docUri, template);
                                File.WriteAllText(localPath, rdoc.ToString());
                                SaveImage(rdoc, false, null);
                            }

                        }
                    };
                }
            }
            else
            {
                //从缓存拷贝到loacl
                XDocument rdoc = XDocument.Parse(File.ReadAllText(cachePath));
                string loaclPath = ReaderPath.GetSiteFileName(docUri);
                if (!File.Exists(loaclPath))
                {
                    File.Copy(cachePath, loaclPath);
                    if (IsImageContent(rdoc))
                    {
                        foreach (XElement image in GetImage(rdoc))
                        {
                            string imagePath = image.Attribute("Source").Value;
                            string localImage= Path.Combine(Path.GetDirectoryName(loaclPath),Path.GetFileName(imagePath));
                            File.Copy(imagePath,localImage);
                        }
                    }
                }
            }
        }
        private static void WriteNextChapterCache(XDocument rdoc,string template, int count, bool isNext)
        {
            if (isNext)
            {
                if (!string.IsNullOrEmpty(GetNextUri(rdoc)) && (GetNextUri(rdoc) != GetContentUri(rdoc)))
                {
                    if (Uri.IsWellFormedUriString(GetNextUri(rdoc), UriKind.Absolute))
                    {
                        WriteChapterCache(GetNextUri(rdoc), template, count - 1, true);
                    }
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(GetPreviousUri(rdoc)) && GetPreviousUri(rdoc) != GetContentUri(rdoc))
                {
                    if (Uri.IsWellFormedUriString(GetPreviousUri(rdoc), UriKind.Absolute))
                    {
                        WriteChapterCache(GetPreviousUri(rdoc), template, count - 1, false);
                    }
                }
            }
        }
        public static void WriteQidianCache(XDocument chapterDoc,string chapterUri,string template)
        {
            if (new Uri(chapterUri).Host == "www.qidian.com")
            {
                string textUri = GetTextUri(chapterDoc);
                if (!string.IsNullOrEmpty(textUri))
                {
                    if (Uri.IsWellFormedUriString(textUri, UriKind.Absolute))
                    {
                        WebClient client = new WebClient();
                        client.Encoding = new Gb2312Encoding();
                        client.DownloadStringAsync(new Uri(textUri));
                        client.DownloadStringCompleted += (s, args) =>
                        {
                            if (args.Error == null)
                            {
                                XDocument textDoc = GenerateChapterXaml(args.Result, textUri, template);
                                string path = Path.Combine(ReaderPath.CacheDirectory, ReaderPath.ConvertToWinPath(textUri));
                                File.WriteAllText(path, textDoc.ToString());
                                //不论是否最后一章没有影响都缓存最大时间
                                Cache.Current.Add(textUri, path, ReaderConfig.MaxCacheTime);
                               
                            }
                        };
                    }
                }
            }
            
        }
        /// <summary>
        /// 自动把章节加载到缓存
        /// </summary>
        /// <param name="docUri"></param>
        /// <param name="template"></param>
        /// <param name="count"></param>
        /// <param name="isNext"></param>
        public static void WriteChapterCache(string docUri, string template, int count, bool isNext)
        {
            if (count > 0)
            {
                string docPath = "";
                if (!Cache.Current.TryGet(docUri, out docPath))
                {
                    //解析不正确，会导致docUri错误，正常应该不出现
                    if (Uri.IsWellFormedUriString(docUri, UriKind.Absolute))
                    {
                        WebClient client = new WebClient();
                        client.Encoding = new Gb2312Encoding();
                        client.DownloadStringAsync(new Uri(docUri));
                        client.DownloadStringCompleted += (s, args) =>
                        {
                            if (args.Error == null)
                            {
                                XDocument rdoc = BookChapter.GenerateChapterXaml(args.Result, docUri, template);
                                if (docUri != GetContentUri(rdoc))
                                {
                                    docPath = Path.Combine(ReaderPath.CacheDirectory, ReaderPath.ConvertToWinPath(docUri));
                                    WriteQidianCache(rdoc, docUri, template);
                                    File.WriteAllText(docPath, rdoc.ToString());
                                    if (BookChapter.IsEnd(rdoc))
                                    {
                                        Cache.Current.Add(docUri, docPath, ReaderConfig.MinCacheTime);
                                        BookChapter.SaveImage(rdoc, true, ReaderConfig.MinCacheTime);
                                    }
                                    else
                                    {
                                        Cache.Current.Add(docUri, docPath, ReaderConfig.MaxCacheTime);
                                        BookChapter.SaveImage(rdoc, true, ReaderConfig.MaxCacheTime);
                                    }
                                    WriteNextChapterCache(rdoc, template, count, isNext);
                                }

                            }
                        };
                    }
                    else
                        throw new Exception(docUri+"格式不正确");
                }
                else
                {
                    
                    XDocument doc = XDocument.Parse(File.ReadAllText(docPath));
                    //使count个uri都测试一遍
                    WriteNextChapterCache(doc, template, count, isNext);
                }

            }
        }
    

    }
}
